package com.snif.web.attach.core.server;

import com.snif.web.attach.core.RequestHandler;
import com.snif.web.attach.core.utils.LogUtils;
import com.sun.net.httpserver.HttpServer;
import lombok.extern.slf4j.Slf4j;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;


public class ConfigurablePortHttpServer {

	// 默认基础端口和最大重试次数
	private static final int DEFAULT_BASE_PORT = 8080;

	private static final int MAX_RETRIES = 100;

	private HttpServer httpServer;

	private int boundPort; // 实际绑定的端口

	/**
	 * 启动HTTP服务器，支持指定固定端口或动态获取
	 * @param specifiedPort 指定的端口（null或<=0则使用动态端口）
	 * @return 实际绑定的端口号
	 * @throws IOException 启动失败
	 */
	public int start(Integer specifiedPort) throws IOException {
		// 1. 确定要使用的端口
		if (specifiedPort != null && specifiedPort > 0) {
			// 验证指定端口是否可用
			if (isPortAvailable(specifiedPort)) {
				boundPort = specifiedPort;
			}
			else {
				throw new IOException("指定的端口 " + specifiedPort + " 已被占用");
			}
		}
		else {
			// 动态查找可用端口
			boundPort = findAvailablePort(DEFAULT_BASE_PORT, MAX_RETRIES);
			if (boundPort == -1) {
				throw new IOException(
						"在端口范围 " + DEFAULT_BASE_PORT + "-" + (DEFAULT_BASE_PORT + MAX_RETRIES) + " 内未找到可用端口");
			}
		}

		// 2. 绑定端口并启动服务
		httpServer = HttpServer.create(new InetSocketAddress(boundPort), 0);
		httpServer.createContext("/func/index", new RequestHandler());
		httpServer.setExecutor(null); // 使用默认执行器
		httpServer.start();

		LogUtils.info("探针HTTP服务已启动，端口：" + boundPort);
		// 保存端口到系统属性，方便其他地方获取
		// System.setProperty("probe.http.port", String.valueOf(boundPort));
		return boundPort;
	}

	/**
	 * 查找可用端口
	 */
	private int findAvailablePort(int basePort, int maxRetries) {
		for (int i = 0; i < maxRetries; i++) {
			int port = basePort + i;
			if (isPortAvailable(port)) {
				return port;
			}
		}
		return -1;
	}

	/**
	 * 检查端口是否可用
	 */
	private boolean isPortAvailable(int port) {
		try (ServerSocket socket = new ServerSocket(port)) {
			socket.setReuseAddress(true); // 允许端口快速重用
			return true;
		}
		catch (IOException e) {
			return false;
		}
	}

	/**
	 * 停止服务器
	 */
	public void stop() {
		if (httpServer != null) {
			httpServer.stop(0);
			LogUtils.info("探针HTTP服务已停止，端口：" + boundPort);
		}
	}

	public int getBoundPort() {
		return boundPort;
	}

}
